/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package Server.domain;

import java.util.ArrayList;
import java.util.List;

/**
 *
 * @author Ripper
 */
public class GameSession implements Runnable
{
    private ServerDomainController sdc;
    
    private int dungeonMasterIndex;
    
    private List<User> players;
    private List<Boolean> playerReady;
    
    private List<String> whatToTell;
    
    private GameLevel gameLevel;
    
    private String sessionName;
    
    private boolean inSession;
    
    public GameSession(ServerDomainController sdcc, String sesName)
    {
        sdc = sdcc;
        players = new ArrayList<User>();
        playerReady = new ArrayList<Boolean>();
        whatToTell = new ArrayList<String>();
        gameLevel = new GameLevel(this);
        
        dungeonMasterIndex = -1;
        
        sessionName = sesName;
        inSession = false;
    }
    
    public void tellGameSession(String info)
    {
        if(inSession)
        {
            for(int a = 0;a < whatToTell.size(); a++)
            {
                String data = whatToTell.get(a);

                data += ";" + info;

                whatToTell.set(a, data);
            }
        }
    }
    
    public String playerAsksForData(User u)
    {
        String data = "";
        
        data += getGlobalData() + ";";
        
        int index = getIndexOfPlayer(u);
        if(index != -1)
        {
            Player p = u.getSelectedPlayer();
            
            data += "hitpoints:"+p.getHitpoints()+"/"+p.getMaxHitpoints()+";"+
                    "mana:"+p.getManapoints()+"/"+p.getMaxManapoints()+";"+
                    "stam:"+p.getStaminapoints()+"/"+p.getMaxStaminapoints()+";"+
                    "xloc:"+p.getX()+";yloc:"+p.getY()+";";
            
            data += whatToTell.get(index);
            whatToTell.set(index, "");
            
            return data;
        }
        else
        {
            return "";
        }
    }
    
    public void playerSays(Player speaker, String text)
    {
        String plr = speaker.getPlayerName();
        
        if(dungeonMasterIndex != -1)
        {
            Player dm = getPlayerAtIndex(dungeonMasterIndex).getSelectedPlayer();
            
            if(dm != null && dm.getPlayerName().equals(speaker.getPlayerName()))
            {
                plr += " (DM)";
            }
        }
        
        playerSays(plr, text);
    }
    public void playerSays(String plrNm, String text)
    {
        tellGameSession("plrSpoken:"+plrNm+"="+text);
    }
    public void playerClicks(Player p, String data)
    {
        String[] dat = data.split(",");
        int x = Integer.parseInt(dat[0]);
        int y = Integer.parseInt(dat[1]);
        
        //TODO: determin attack angle
        double attackDirection = MathHelper.getAngle(p, (double)x, (double)y);
        
        p.setAttackDirection(attackDirection);
        
        p.attack(attackDirection);
        //gameLevel.playerAttacks(p);
    }
    
    public String getGlobalData()
    {
        return gameLevel.getGlobalLocationData();
    }
    
    public String getSessionName()
    {
        return sessionName;
    }
    public int getSessionPlayerCount()
    {
        int count = 0;
        for(User u: players)
        {
            if(!(u instanceof AIDungeonMasterUser))
            {
                count++;
            }
        }
        return count;
    }
    public boolean isSessionReadyToStart()
    {
        if(inSession)
        {
            return false;
        }
        
        for(boolean b: playerReady)
        {
            if(!b)
            {
                return false;
            }
        }
        
        if(dungeonMasterIndex == -1)
        {
            return false;
        }
        
        if(players.size() < 2)
        {
            return false;
        }
        
        return true;
    }
    
    public void playerConnects(User u)
    {
        if(u.getPlayers().size() > 0)
        {
            players.add(u);
            Player charac = u.getSelectedPlayer();
            
            gameLevel.addPlayer(charac);
            
            if(inSession)
            {
                playerReady.add(true);
                charac.prepareForBattle(gameLevel, 0, 0);
                whatToTell.add(""+gameLevel.getNewConnectionInformation());
            }
            else
            {
                playerReady.add(false);
            whatToTell.add("");
            }
        }
    }
    public User getPlayerAtIndex(int i)
    {
        try
        {
            return players.get(i);
        }
        catch(Exception ex)
        {
            return null;
        }
    }
    public int getIndexOfPlayer(User u)
    {
        int index = 0;
        for(User uu: players)
        {
            if(uu == u)
            {
                return index;
            }
            index++;
        }
        return -1;
    }
    public boolean isPlayerReady(User u)
    {
        return playerReady.get(getIndexOfPlayer(u));
    }
    public boolean playerSignsupAsDungeonMaster(User u)
    {
        if(dungeonMasterIndex == -1)
        {
            if(players.contains(u))
            {
                dungeonMasterIndex = getIndexOfPlayer(u);
                
                gameLevel.removePlayer(u.getSelectedPlayer());
                return true;
            }
        }
        return false;
    }
    public boolean playerSignsoffAsDungeonMaster(User u)
    {
        if(u == getPlayerAtIndex(dungeonMasterIndex))
        {
            dungeonMasterIndex = -1;
            
            gameLevel.addPlayer(u.getSelectedPlayer());
            return true;
        }
        return false;
    }
    public void playerDisconnects(User u)
    {
        if(players.contains(u))
        {
            int index = getIndexOfPlayer(u);
            players.remove(index);
            playerReady.remove(index);
            whatToTell.remove(index);
            
            if(index == dungeonMasterIndex)
            {
                dungeonMasterIndex = -1;
            }
            else 
            {
                gameLevel.removePlayer(u.getSelectedPlayer());
            }
        }
    }
    public void playerReadiesUp(User u)
    {
        int index = getIndexOfPlayer(u);
        playerReady.set(index, true);
    }
    public void playerCancelsReadyUp(User u)
    {
        int index = getIndexOfPlayer(u);
        playerReady.set(index, false);
    }
    public void assignAIDungeonMaster(int index)
    {
        //TODO
    }
    
    @Override
    public void run()
    {
        startSession();
        //TODO ?
        
        boolean running = true;
        
        long timeStart = 0;
        long timeTaken = 0;
        long sleepyTime = 0;
        while(running)
        {
            timeStart = System.currentTimeMillis();
            gameLevel.update();
            
            if(getPlayerAtIndex(dungeonMasterIndex) instanceof AIDungeonMasterUser)
            {
                //TODO: update the AI dungeon master so he can do stuff
            }
            timeTaken = System.currentTimeMillis() - timeStart;
            if(timeTaken < 10)
            {
                sleepyTime = 10 - timeTaken;
            }
            
            try
            {
                Thread.sleep(sleepyTime);
            }
            catch(Exception ex) { }
        }
    }
    
    public void startSession()
    {
        double spawnx = 0;
        double spawny = 0;
        int plrcount = 0;
        for(Player p: gameLevel.getPlayers())
        {
            plrcount++;
            p.prepareForBattle(gameLevel, plrcount * 50 + spawnx, spawny);
        }
        gameLevel.prepareSpawnArea();
                
        inSession = true;
        tellGameSession(gameLevel.getNewConnectionInformation());
        
        //TODO ?
    }
    
    public void endSession()
    {
        sdc.endGameSession(this);
    }
    
    public String getLobbyData()
    {
        if(!inSession)
        {
            String data = "";

            for(int a = 0; a < players.size(); a++)
            {
                User u = players.get(a);

                if(a == dungeonMasterIndex)
                {
                    data += "dm:";
                }
                else
                {
                    data += "p:";
                }
                data += u.getUsername()+ ","+(playerReady.get(a)?"ready":"notready")+"-";
            }

            data = data.substring(0, data.length()-1);
            
            return data;
        }
        else
        {
            return "gamestarting";
        }
    }
}
